#include "junix.h"

namespace jsearch
{

/***********************************************************************/
/*this is APUE style error process function, Not safe in thread.(exit)   */
/***********************************************************************/
void err_sys(const char *fmt, ...)
{
	va_list ap;

	va_start(ap, fmt);
	vfprintf(stderr, fmt, ap);
	fprintf(stderr, ": %s\n", strerror(errno));
	va_end(ap);

	exit(1);
}

void err_quit(const char *fmt, ...)
{
	va_list ap;

	va_start(ap, fmt);
	vfprintf(stderr, fmt, ap);
	fputs("\n", stderr);
	va_end(ap);
	exit(1);
}

void err_ret(const char *fmt, ...)
{
	va_list ap;

	va_start(ap, fmt);
	vfprintf(stderr, fmt, ap);
	fputs("\n", stderr);
	va_end(ap);
}
/**********************************************************************/
/* Wrappers for UNIX IO */
/**********************************************************************/
int Open(const char *path, int oflag, ... )
{
	int fd;
	va_list ap;

	va_start(ap,oflag);
	fd=open(path,oflag,ap);
	va_end(ap);

	if(fd==-1)
		err_sys("open");

	return fd;
}

int Close(int fd)
{
	if( close(fd) == -1)
		err_sys("close");

	return 0;
}

ssize_t Read(int fd, char *buf, size_t len)
{
	ssize_t sz;
	while( (sz=read(fd,buf,len))==-1 && errno == EINTR)
	{}

	if(sz==-1)
		err_sys("read");

	return sz;
}

ssize_t Write(int fd, char *buf, ssize_t  len)
{
	ssize_t sz;
	while( (sz=write(fd,buf,len)) != len && errno==EINTR)
	{}

	if(sz != len)
		err_sys("write");

	return len;
}

off_t Lseek(int fd, off_t offset, int where)
{
	off_t off = lseek(fd,offset,where);
	if(off<0)
		err_sys("lseek");

	return off;
}


int Select(int maxfd, fd_set *rdset, fd_set *wrset,
		fd_set *exset, struct timeval *tv)
{
	int ret=select(maxfd, rdset, wrset, exset, tv);
	if(ret<0)
		err_sys("select");

	return ret;
}

int Dup2 (int o, int n)
{
	int  rc=dup2(o,n);
	if(rc<0)
		err_sys("dup2");

	return rc;
}

/*********************************************/
//  ReadLine Readn Writen
/*********************************************/
char *readline(int fd,char *buf, size_t sz)
{
	int ch,ret;
	char *p=buf, *q=buf+sz-2;
	if(buf==NULL || sz<3)
		err_quit("jreadline buf is NULL");

	while(p!=q){
		ret=Read(fd,(char*)&ch,1);
		if(ret==0){
			if(p==buf)
				return NULL;
			break;
		}else{
			if(ch=='\n')
				break;
			*p++=ch;
		}
	}

	*p++='\n';
	*p='\0';
	return buf;
}

/*readn*/
ssize_t readn(int fd, char *buf, size_t sz)
{
	size_t left=sz,len;
	char *p=buf;

	if(buf==NULL)
		err_quit("buf is NULL");

	while( (len=Read(fd,p,left))>0){
		p += len;
		left -= len;
		if( !left )
			break;
	}

	return  (sz-left);
}

/**writen*/
ssize_t writen(int fd, char *buf, ssize_t sz)
{
	char *p=buf;
	ssize_t left=sz,len;

	while(left>0)
	{
		while( (len=write(fd,p,left))==-1 && errno==EINTR )
		{}

		if(len == -1)
			err_sys("write");

		p += len;
		left -= len;
	}

	return sz;
}

}//end namespace
